#include <linux/cdev.h>
#include <linux/kobject.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

static struct kset *kset;
static struct kobject *kobj1;
static struct kobject *kobj2;

static unsigned int val = 10;

ssize_t val_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) {
	return snprintf(buf, PAGE_SIZE, "%d\n", val);
}

ssize_t val_store(struct kobject *kobj, struct kobj_attribute *attr,
		const char *buf, size_t count) {
//	char *endp;
//	printk("size = %d\n", (int )count);
//	val = simple_strtoul(buf, &endp, 10);
	val  =  20;
	return count;
}

static struct kobj_attribute kobj1_val_attr = { { .name = __stringify(val),
		.mode = 0666 }, .show = val_show, .store = val_store };

static struct attribute *kobj1_attrs[] = { &kobj1_val_attr.attr,
NULL, };

static struct attribute_group kobj1_attr_group = { .attrs = kobj1_attrs };

int my_close(struct inode *inode, struct file *file) {
	pr_info("a3 my_close\n");
	return 0;
}

const struct file_operations my_fops = { .owner = THIS_MODULE, .release =
		my_close, };

static __init int my_init(void) {
	int ret;
	pr_info("a3 init_module\n");
	kset = kset_create_and_add("dir", NULL, NULL);
	kobj1 = kobject_create_and_add("a", &kset->kobj);
	kobj2 = kobject_create_and_add("b", &kset->kobj);
	ret = sysfs_create_group(kobj1, &kobj1_attr_group);
	if (ret < 0) {
		pr_err("sysfs_create_group failed\n");
		return ret;
	}
	ret = sysfs_create_link(kobj2, kobj1, "link");
	if (ret < 0) {
		pr_err("sysfs_create_link failed\n");
		return ret;
	}
	pr_info("sysfs_create_link\n");
	return ret;
}

static void __exit my_exit(void) {
	pr_info("my_exit\n");
	sysfs_remove_link(kobj2, "link");
	kobject_del(kobj2);
	kobject_del(kobj1);
	sysfs_remove_group(kobj1, &kobj1_attr_group);
	kset_unregister(kset);
}

module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andy");
MODULE_DESCRIPTION("A sample c  driver");
